import { base64Decode, decodeCharset, qpDecode } from 'coremail/src/main/ets/utils/encodings';
import type { IBuffer, Mime,
} from 'coremail/Index';
import { getMimeDecodedBody } from 'coremail/src/main/ets/utils/mime';
import { FileBuffer } from '../basedata/FileBuffer';
import { StringUtil } from './StringUtil';
import { ExtVsMimeDict } from './MimeExtMap';
import { FileUtil } from './FileUtil';

export class ParseUtil {
  static async decodeMimePartToString(part: Mime): Promise<string> {
    let b: Uint8Array | undefined = await ParseUtil.decodeMimePartToBlob(part);
    let s = "";
    if (b) {
      const decodedString = decodeCharset(b, part.contentType.params.charset || "utf-8");
      if (decodedString.length) {
        s = decodedString;
      }
    }
    part.encoding = 'utf-8';
    return s;
  }

  static async decodeMimePartToBlob(part: Mime): Promise<Uint8Array> {
    const stream = part.body;
    const ss: string[] = [];
    for await (const chunk of stream) {
      ss.push(chunk);
    }
    let s: string = ss.join("");
    let b: Uint8Array | undefined;
    if (part.encoding == "base64") {
      b = base64Decode(s);
    } else if (part.encoding == "quoted-printable") {
      b = qpDecode(s);
    }
    return b
  }


  /**
   * 返回一个以指定filePath创建的IBuffer
   * @param part
   * @param filePath
   * @returns
   */
  static async decodeMimePartToBuffer(part: Mime,filePath:string): Promise<IBuffer> {
    let buffer = getMimeDecodedBody(part);
    part.encoding = '8bit';
    FileUtil.mkFileDirRecursively(filePath);
    const f = new FileBuffer(filePath);

    for await (const chunk of buffer.readRaw()) {
      await f.feed(chunk);
    }
    await f.end();
    return f;
  }

  /**
   * 生成存于本地沙盒的文件名
   * @param id 文件id
   * @param name 文件名
   * @param fileType 文件后缀名
   * @returns 文件存于本地沙盒时的名字
   * @description 文件名可为空，或者不带后缀，或者有额外字符串等情况，存本地需要转换为hash值统一替换
   * @discuss fileType应该是返回准确文件后缀名，但SDK可能是解析出来是对照MIMEType(例如svg为image/svg+xml，传入的fileType为subtype:svg+xml)，所以需要做一次转换
   */
  static uniqName(id: string, name: string | null, fileType: string | null): string {
    let cid = StringUtil.getCid(id)
    let fname = name || cid
    let hashCode = StringUtil.hashCode(fname)
    if (fileType) {
      let ext = Object.entries(ExtVsMimeDict).find(item => item[1].endsWith(fileType))
      if (ext) {
        return `${hashCode}.${ext[0]}`
      }
    }
    return `${hashCode}`
  }
}
